/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.gallery3d.ui;

import com.android.gallery3d.app.AbstractGalleryActivity;
import com.android.gallery3d.app.AlbumDataLoader;
import com.android.gallery3d.data.MediaObject;
import com.android.gallery3d.data.Path;
import com.android.gallery3d.glrenderer.ColorTexture;
import com.android.gallery3d.glrenderer.FadeInTexture;
import com.android.gallery3d.glrenderer.GLCanvas;
import com.android.gallery3d.glrenderer.Texture;
import com.android.gallery3d.glrenderer.TiledTexture;

public class AlbumSlotRenderer extends AbstractSlotRenderer {
	private static final String TAG = AlbumSlotRenderer.class.getSimpleName();

	public interface SlotFilter {
		public boolean acceptSlot(int index);
	}

	private final int mPlaceholderColor;
	private static final int CACHE_SIZE = 96;

	private AlbumSlidingWindow mDataWindow;
	private final AbstractGalleryActivity mActivity;
	private final ColorTexture mWaitLoadingTexture;
	private final SlotView mSlotView;
	private final SelectionManager mSelectionManager;

	private int mPressedIndex = -1;
	private boolean mAnimatePressedUp;
	private Path mHighlightItemPath = null;
	private boolean mInSelectionMode;

	private SlotFilter mSlotFilter;

	public AlbumSlotRenderer(AbstractGalleryActivity activity,
			SlotView slotView, SelectionManager selectionManager,
			int placeholderColor) {
		super(activity);
		Log.d(TAG, "AlbumSlotRenderer");
		mActivity = activity;
		mSlotView = slotView;
		mSelectionManager = selectionManager;
		mPlaceholderColor = placeholderColor;

		mWaitLoadingTexture = new ColorTexture(mPlaceholderColor);
		mWaitLoadingTexture.setSize(1, 1);
	}

	public void setPressedIndex(int index) {
		Log.d(TAG, "setPressedIndex -- index: " + index);
		if (mPressedIndex == index)
			return;
		mPressedIndex = index;
		mSlotView.invalidate();
	}

	public void setPressedUp() {
		Log.d(TAG, "setPressedUp");
		if (mPressedIndex == -1)
			return;
		mAnimatePressedUp = true;
		mSlotView.invalidate();
	}

	public void setHighlightItemPath(Path path) {
		Log.d(TAG, "setHighlightItemPath -- path: " + path);
		if (mHighlightItemPath == path)
			return;
		mHighlightItemPath = path;
		mSlotView.invalidate();
	}

	public void setModel(AlbumDataLoader model) {
		Log.d(TAG, "setModel");
		if (mDataWindow != null) {
			mDataWindow.setListener(null);
			mSlotView.setSlotCount(0);
			mDataWindow = null;
		}
		if (model != null) {
			mDataWindow = new AlbumSlidingWindow(mActivity, model, CACHE_SIZE);
			mDataWindow.setListener(new MyDataModelListener());
			mSlotView.setSlotCount(model.size());
		}
	}

	private static Texture checkTexture(Texture texture) {
		return (texture instanceof TiledTexture)
				&& !((TiledTexture) texture).isReady() ? null : texture;
	}

	@Override
	public int renderSlot(GLCanvas canvas, int index, int pass, int width,
			int height) {
		Log.d(TAG, "renderSlot -- index: " + index);

		if (mSlotFilter != null && !mSlotFilter.acceptSlot(index))
			return 0;

		AlbumSlidingWindow.AlbumEntry entry = mDataWindow.get(index);

		int renderRequestFlags = 0;

		Texture content = checkTexture(entry.content);
		if (content == null) {
			content = mWaitLoadingTexture;
			entry.isWaitDisplayed = true;
		} else if (entry.isWaitDisplayed) {
			entry.isWaitDisplayed = false;
			content = new FadeInTexture(mPlaceholderColor, entry.bitmapTexture);
			entry.content = content;
		}
		drawContent(canvas, content, width, height, entry.rotation);
		if ((content instanceof FadeInTexture)
				&& ((FadeInTexture) content).isAnimating()) {
			renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
		}

		if (entry.mediaType == MediaObject.MEDIA_TYPE_VIDEO) {
			drawVideoOverlay(canvas, width, height);
		}

		if (entry.isPanorama) {
			drawPanoramaIcon(canvas, width, height);
		}

		renderRequestFlags |= renderOverlay(canvas, index, entry, width, height);

		return renderRequestFlags;
	}

	private int renderOverlay(GLCanvas canvas, int index,
			AlbumSlidingWindow.AlbumEntry entry, int width, int height) {
		Log.d(TAG, "renderOverlay -- index: " + index);
		int renderRequestFlags = 0;
		if (mPressedIndex == index) {
			if (mAnimatePressedUp) {
				drawPressedUpFrame(canvas, width, height);
				renderRequestFlags |= SlotView.RENDER_MORE_FRAME;
				if (isPressedUpFrameFinished()) {
					mAnimatePressedUp = false;
					mPressedIndex = -1;
				}
			} else {
				drawPressedFrame(canvas, width, height);
			}
		} else if ((entry.path != null) && (mHighlightItemPath == entry.path)) {
			drawSelectedFrame(canvas, width, height);
		} else if (mInSelectionMode
				&& mSelectionManager.isItemSelected(entry.path)) {
			drawSelectedFrame(canvas, width, height);
		}
		return renderRequestFlags;
	}

	private class MyDataModelListener implements AlbumSlidingWindow.Listener {
		@Override
		public void onContentChanged() {
			mSlotView.invalidate();
		}

		@Override
		public void onSizeChanged(int size) {
			mSlotView.setSlotCount(size);
		}
	}

	public void resume() {
		mDataWindow.resume();
	}

	public void pause() {
		mDataWindow.pause();
	}

	@Override
	public void prepareDrawing() {
		mInSelectionMode = mSelectionManager.inSelectionMode();
	}

	@Override
	public void onVisibleRangeChanged(int visibleStart, int visibleEnd) {
		if (mDataWindow != null) {
			mDataWindow.setActiveWindow(visibleStart, visibleEnd);
		}
	}

	@Override
	public void onSlotSizeChanged(int width, int height) {
		// Do nothing
	}

	public void setSlotFilter(SlotFilter slotFilter) {
		mSlotFilter = slotFilter;
	}
}
